export function numberToString(value) {
  let _value = `${value}`;
  if (_value.includes('e')) {
    let sign = '';
    if (_value[0] === '-') {
      sign = '-';
      // 移除负号
      _value = _value.slice(1);
    }
    if (_value.includes('e+')) {
      const [mantissa, exponent] = _value.split('e+');
      let int = `${mantissa[0]}${mantissa.slice(2)}`;
      const length = Number(exponent) + 1;
      int = int.padEnd(length, '0');
      return `${sign}${int}`;
    }
    if (_value.includes('e-')) {
      const [mantissa, exponent] = _value.split('e-');
      let dec = '';
      if (mantissa.includes('.')) {
        dec = `${mantissa[0]}${mantissa.slice(2)}`;
        const length = Number(exponent) + dec.length - 1;
        dec = dec.padStart(length, '0');
      } else {
        const length = Number(exponent);
        dec = mantissa.padStart(length, '0');
      }
      return `${sign}0.${dec}`;
    }
  }
  return _value;
}

function operation(x, y, sign, digits) {
  const _x = numberToString(x);
  const _y = numberToString(y);
  const [xInt, xDec = ''] = _x.split('.');
  const [yInt, yDec = ''] = _y.split('.');
  if (xDec || yDec) {
    const xDecLen = xDec.length;
    const yDecLen = yDec.length;
    let decLen = 0;
    let zBigint = 0n;
    if (sign === '+' || sign === '-') {
      decLen = Math.max(xDecLen, yDecLen);
      const _xDec = xDec.padEnd(decLen, '0');
      const _yDec = yDec.padEnd(decLen, '0');
      const xBigint = BigInt(`${xInt}${_xDec}`);
      const yBigint = BigInt(`${yInt}${_yDec}`);
      if (sign === '+') {
        zBigint = xBigint + yBigint;
      } else {
        zBigint = xBigint - yBigint;
      }
    } else if (sign === '*') {
      decLen = xDecLen + yDecLen;
      const _xDec = xDec.padEnd(xDecLen, '0');
      const _yDec = yDec.padEnd(yDecLen, '0');
      const xBigint = BigInt(`${xInt}${_xDec}`);
      const yBigint = BigInt(`${yInt}${_yDec}`);
      zBigint = xBigint * yBigint;
      zBigint = xBigint * yBigint;
    }

    if (zBigint === 0n) return '0';

    let z = zBigint.toString();
    let minus = '';
    if (z[0] === '-') {
      minus = '-';
      // 移除负号
      z = z.slice(1);
    }

    // 小数点后最大保留 digits 位
    if (decLen > digits) {
      if (decLen - digits > 1) {
        z = z.slice(0, -(decLen - digits - 1));
      }
      const endChar = z[z.length - 1];
      z = z.slice(0, -1);
      // 四舍五人
      if (Number(endChar) >= 5) {
        // 进一
        z = (BigInt(z) + 1n).toString();
      }
      decLen = digits;
    }

    let int = ''; // 整数部分
    let dec = ''; // 小数部分
    if (z.length <= decLen) {
      int = '0';
      dec = z.padStart(decLen, '0');
    } else {
      int = z.slice(0, -decLen);
      dec = z.slice(z.length - decLen);
    }
    // 移除末尾多余的0
    dec = dec.replace(/(?<=(\d*))(0+$)/, '');
    if (dec) {
      return `${minus}${int}.${dec}`;
    }
    return `${minus}${int}`;
  } else {
    const xBigint = BigInt(xInt);
    const yBigint = BigInt(yInt);
    let zBigint = 0n;
    if (sign === '+') {
      zBigint = xBigint + yBigint;
    } else if (sign === '-') {
      zBigint = xBigint - yBigint;
    } else if (sign === '*') {
      zBigint = xBigint * yBigint;
    }
    return zBigint.toString();
  }
}

// 加法
export function addition(x, y, digits = 20) {
  operation(x, y, '+', digits);
}

// 减法
export function subtraction(x, y, digits = 20) {
  operation(x, y, '-', digits);
}

// 乘法
export function multiplication(x, y, digits = 20) {
  operation(x, y, '*', digits);
}

// 除法
export function division(x, y, digits = 20) {
  const _x = numberToString(x);
  const _y = numberToString(y);
  const [xInt, xDec = ''] = _x.split('.');
  const [yInt, yDec = ''] = _y.split('.');
  const _xDecLen = yDec.length + digits + 1;
  const _xDec = xDec.slice(0, _xDecLen).padEnd(_xDecLen, '0');
  const xBigint = BigInt(`${xInt}${_xDec}`);
  const yBigint = BigInt(`${yInt}${yDec}`);
  const zBigint = xBigint / yBigint;

  if (zBigint === 0n) return '0';

  let sign = '';
  let z = zBigint.toString();
  if (z[0] === '-') {
    sign = '-';
    // 移除负号
    z = z.slice(1);
  }

  const endChar = z[z.length - 1];
  z = z.slice(0, -1);
  if (Number(endChar) >= 5) {
    // 进一
    z = (BigInt(z) + 1n).toString();
  }

  let int = ''; // 整数部分
  let dec = ''; // 小数部分
  if (z.length <= digits) {
    int = '0';
    dec = z.padStart(digits, '0');
  } else {
    int = z.slice(0, -digits);
    dec = z.slice(z.length - digits);
  }
  // 移除末尾多余的0
  dec = dec.replace(/(?<=(\d*))(0+$)/, '');
  if (dec) {
    return `${sign}${int}.${dec}`;
  }
  return `${sign}${int}`;
}

// 四舍五入
export function round(value, digits = 2, fill = false) {
  if (!value && value !== 0) return '';
  const str = numberToString(value);
  const [int, dec] = str.split('.');
  let _int = int;
  let _dec = dec || '';
  if (_dec.length > digits) {
    let sign = '';
    if (_int[0] === '-') {
      sign = '-';
      // 移除负号
      _int = _int.slice(1);
    }
    // 第 digits + 1 位的数字
    const num = Number(_dec[digits]);
    let bigint = 0n;
    if (digits) {
      // 截取小数部分的前digits位
      _dec = _dec.slice(0, digits);
      bigint = BigInt(`${_int}${_dec}`);
    } else {
      bigint = BigInt(_int);
    }

    // 四舍五入
    if (num >= 5) {
      // 进一
      bigint += 1n;
    }
    const res = bigint.toString();
    if (digits) {
      if (res.length <= digits) {
        _int = `${sign}0`;
        _dec = res.padStart(digits, '0');
      } else {
        _int = sign + res.slice(0, -digits);
        _dec = res.slice(res.length - digits);
      }
    } else {
      _int = `${sign}${res}`;
      _dec = '';
    }
  } else if (digits && fill) {
    // 末尾填充0
    _dec = _dec.padEnd(digits, '0');
  }
  if (!fill) {
    // 移除末尾多余的0
    _dec = _dec.replace(/(?<=(\d*))(0+$)/, '');
  }
  if (_dec) {
    return `${_int}.${_dec}`;
  }
  return _int;
}
